By August Mohr and Marco C. Mason
Sometimes you or your computer accidentally creates a file that has unusual characters in its name. Depending on the nature of the error and the application that created it, such a file might have control characters, quotes, tabs, or even new line characters within the name. Cleaning up such an error by removing the file can prove difficult, but it should be possible using one of the following techniques.
As you know, some characters have special meaning in the shell. These include the wildcard characters * and ?, quotation marks, parentheses, and the ampersand. If the filename contains characters like these that are special to the shell, all the characters of the filename may be visible in an ls listing, but you can't remove the file simply by typing the name as displayed.
Suppose you have a file named T&Bar\Vee in your
directory that you want to remove. Your first impulse would be
to use the rm command like this:
$ rm T&Bar\Vee
338
BarVee: not found
You can remove the file (or rename it with the mv
command) by typing a backslash (\) before each special character.
This tells the shell to treat the next character as a normal character.
(This is why the \ didn't appear in the error message above; \V
told the shell to treat the V as a V. In effect, the \ was ignored.)
Since the backslash is a special character as well, a filename
containing a backslash will need two of them. For example, to
remove a file named T&Bar\Vee, you'll need to
put a backslash before both the special characters & and \
in your rm command:
$ rm T\&Bar\\Vee
One common, but easy to deal with, case is a filename that begins
with a dash (-), such as -foo. If you just try the obvious
rm command, an error will occur:
$ rm -foo
rm: illegal option--0
rm: illegal option--0
usage: rm [-fiRr] file ...
This is because a dash introduces rm options, in this case, -f, -o, and another -o. There is a -f option to rm, but no -o, so rm complains. Even if it didn't, it still wouldn't remove your file named -foo. It would only set the specified options in preparation to deleting the file(s) specified, in this case, none.
There are many possible solutions, but the easiest one in this
case is to precede the filename with ./. This simply specifies
that the file is in the current directory. While this is what
rm defaults to, adding the ./ to the start of the filename keeps
rm from processing the filename as a set of switches because
the dash is no longer the first character in the filename:
$ rm ./-foo
If the filename contains non-printing characters, such as control characters or spaces, that condition may show up in an ls listing that doesn't properly align in columns. If you're really unlucky, the filename contains the character sequence that clears your screen (e.g., the single character [Ctrl]L on the console). Every time the filename is printed, your screen clears.
One way of identifying the erroneous characters is to put the output of ls into a file and then examine the file with vi. Using the :set list command in vi will show where the lines end with a $ and let you identify embedded tabs and trailing spaces.
There are two options to the ls command that can also be helpful in identifying files with non-printing characters in their filenames. These are the -b and -q options. The -b option displays non-printing characters as three-digit octal values preceded by a \ character, and the -q flag causes them to be displayed as question marks. When you know where the non-printing characters are in the name, you can match those characters with shell wild card characters.
For instance, in a directory containing a file with the name foo^Lbar (with an embedded [Ctrl]L character), an ls command would just clear the screen, leaving just "bar" in the upper-left corner. Using ls -b would display it as foo\014bar and using ls -q would produce foo?bar. Knowing there is only one erroneous character, you could then remove the file with the command rm foo?bar (assuming no other files matched the foo?bar pattern).
You can also use the -i (interactive) flag for the rm command. Using the command rm -i * will prompt you for a y or n response for each file in the current directory. You simply respond with an n to each file except the ones you want to remove. You can use leading and trailing characters with the * to narrow the choices (e.g., rm -r f*r will offer you only files that begin with f and end with r).
You can copy all the valid files to another directory (not a subdirectory of the one with the problem). Then you can remove the troublesome file with the rest of the original directory using the command rm -r directory_name. Then you can re-create the directory and move the remaining files back.
If you're running OpenWin or the CDE environment, you can use the File Manager to delete the files. First, you must select the file(s) to delete. Then, in the OpenWin environment, select Delete from the Edit menu. In the CDE environment, choose Put in Trash from the Selected menu.
You can also use the find command to remove files using its -inum and -ok arguments. Using -inum followed by an inode number will match the file with that number. The -ok argument to find is similar to the -exec argument, except that it prompts you for confirmation before executing each command. Note that this wonÃt work well with filenames that have characters such as [Ctrl]L that affect the display.
To use find with the -inum option, first type ls -i. This will
give you the inode numbers of all the files in the directory.
Find the inode number of the problem file. Now, to delete the
file, enter the command
$ find . -inum number -ok
rm {} \;
where number is the inode number of the file you want to remove. You'll then be prompted to confirm whether you want to remove the file.
Another very special case occurs when the file contains an actual slash (/) in its name. This isn't supposed to happen--slashes separate the components of a name and are never supposed to occur within a name. In fact, you can't create such a file--the system won't let you. Nor can you remove such a file--the slash, no matter how you type it in, will be interpreted as a component separator.
Filenames with embedded slashes can only occur as a result of a catastrophic system failure. Extreme action is needed to remove them using the clri command. You can't use clri on a mounted file system, so this technique won't work on the root file system. See the next section, "Files Containing a / in Your Root File System," for additional instructions if your file exists in the root file system.
First, find the inode number using the ls -i command. Write this number down carefully. Next use the shutdown command to enter system maintenance mode. You should double-check that the file system in question has been unmounted. If it hasn't, use umount to unmount it. Clear the inode using the clri command.
Suppose for a moment that we have a file named gesoren/platz
in our /var/x directory. Suppose further that the /var
directory is the mount point for our /dev/dsk/c0t0d0s6
file system. Using ls -i, we find that the inode number of gesoren/platz
is 2345. We put the system in system maintenance mode and unmount
the /var file system. Now we can clear the inode with the
command
# clri /dev/dsk/c0t0d0s6 2345
This command deallocates the inode and puts it on the free list.
However, clri doesn't remove the entry from the directory. The
directory entry that you couldn't remove is still pointing to
the inode that's now on the free list. This is a potentially dangerous
situation. Before you do anything else, run fsck on the affected
file system. For the example above, run
# fsck -F ufs /dev/dsk/c0t0d0s6
and fsck will detect and repair the file system structure inconsistencies
caused by our running the clri command. When it finds the directory
entry that we cleared with clri, it will show some information
like this:
# fsck -F ufs /dev/dsk/c0t0d0s6
** /dev/dsk/c0t0d0s6
** Currently Mounted on /a
** Phase 1 - Check Blocks and Sizes
** Phase 2 - Check Pathnames
UNALLOCATED I=2345 OWNER=root MODE=0
SIZE=0 MTIME=Dec 31 19:00 1969
NAME=/gesoren/platz
REMOVE?
Here, fsck is telling you
that it found a directory entry for file /gesoren/platz
using the unallocated inode numbered 2345. It wants to know if
it should remove the directory entry. At the REMOVE? prompt,
type y and press [Enter]. The fsck
command will delete the directory entry and continue to scan your
disk drive. Near the end, you'll get another warning:
** Phase 3 - Check Connectivity
** Phase 4 - Check Reference Counts
** Phase 5 - Check Cyl groups
FREE BLK COUNT(S) WRONG IN SUPERBLK
SALVAGE?
Now fsck is telling you that the number of free blocks calculated
doesn't match the number of free blocks in the superblock. (The
clri command didn't update the free block count in the superblock
when it cleared the block.) It's asking if it can fix the count
in the superblock. Again, type y and press [Enter]. Then
fsck will finish fixing the errors on your drive:
22925 files, 394588 used,
1731393 free (3137 frags, 216032 blocks, 0.1% fragmentation)
***** FILE SYSTEM WAS MODIFIED
*****
Warning: Running clri in multi-user mode, running clri on a mounted file system, or failing to run fsck immediately after running clri can cause file system corruption, leading to data loss.
Since the clri command works properly only on an unmounted file system, we need a way to run Solaris without mounting our root file system. For more information on this, see the article "Starting Solaris x86 in Single-User Mode" in the March issue of Inside Solaris.
You can use the basic technique described in that article to boot Solaris in maintenance mode from the CD-ROM. From there, you can execute the clri command to clear the specified inode and then run the fsck command as described in the previous section.
As with many things in Solaris, there are techniques you can use to accomplish a seemingly impossible task. In this article, we've tried to show you several ways you can solve the problem of removing files with unexpected characters in their names.
[Return to Index for Inside Solaris - May 1996 Issue]
Copyright (c) 1996 The Cobb Group, a division of Ziff-Davis Publishing Company. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of Ziff-Davis Publishing Company is prohibited. The Cobb Group and The Cobb Group logo are trademarks of Ziff-Davis Publishing Company.
1-800-223-8720